/*
        实用工具类的实现
        1.获取系统时间
        2.判断文件是否存在
        3.获取文件路径
        4.创建目录
*/

// 类成员函数全部采用静态化,便于不用创建对象直接调用

#ifndef __UTIL_HPP__

#define __UTIL_HPP__

#include <ctime>
#include <iostream>
#include <memory>
#include <string>
#include <sstream>
#include <cassert>
#include <sys/stat.h>
#include <jsoncpp/json/json.h>

namespace Log
{
    namespace util
    {
        class date
        {
        public:
            static size_t getTime()
            {
                return (size_t)time(nullptr);
            }
        };

        class file
        {
        public:
            static bool exist(const std::string &pathname)
            {
                struct stat st;
                // 获取文件信息参数,如果成功返回0(即文件存在)否则-1
                // 该函数可跨平台
                return stat(pathname.c_str(), &st) == 0;
            }
            static std::string path(const std::string &pathname)
            {
                // 查找文件路径,例如a/b/c/d.txt则返回a/b/c
                // 考虑到跨平台性即查找'/'和'\'
                int pos = pathname.find_last_of("\\/");
                if (pos == std::string::npos)
                    return ".";
                else
                    return pathname.substr(0, pos + 1);
            }
            static void creatDirectory(const std::string &pathname)
            {
                int head = 0;
                int pos = 0;
                while (head < pathname.size())
                {
                    pos = pathname.find_first_of("/\\", head);

                    if (pos == std::string::npos) // 说明父级目录已经全部存在
                    {
                        mkdir(pathname.c_str(), 0777);
                        break;
                    }
                    std::string parent_dir = pathname.substr(0, pos);
                    if (exist(parent_dir) == true)
                    {
                        head = pos + 2;
                        continue;
                    }
                    mkdir(parent_dir.c_str(), 0777);
                    head = pos + 2;
                }
            }
        };

        class JsonUtil
        {
        public:
            static bool Serialize(Json::Value &root, std::string *str)
            {
                Json::StreamWriterBuilder builder;
                std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());

                std::stringstream ss;
                if (writer->write(root, &ss) != 0)
                {
                    std::cout << "序列化失败!!!\n";
                    return false;
                }
                *str = ss.str();
                return true;
            }

            static bool UnSerialize(Json::Value &root, const std::string *str)
            {
                Json::CharReaderBuilder builder;
                std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

                std::string err;
                if (reader->parse(str->c_str(), str->c_str() + str->size(), &root, &err) == false)
                {
                    std::cout << "反序列化内容失败!!!\n";
                    return false;
                }
                return true;
            }
        };

    };

    class JsonUtil
    {
    public:
        static bool Serialize(Json::Value &root, std::string *str)
        {
            Json::StreamWriterBuilder builder;
            std::unique_ptr<Json::StreamWriter> writer(builder.newStreamWriter());

            std::stringstream ss;
            if (writer->write(root, &ss) != 0)
            {
                return false;
            }
            *str = ss.str();
            return true;
        }

        static bool UnSerialize(Json::Value &root, const char *str, size_t len)
        {
            Json::CharReaderBuilder builder;
            std::unique_ptr<Json::CharReader> reader(builder.newCharReader());

            std::string err;
            if (reader->parse(str, str + len, &root, &err) == false)
            {
                assert(false);
                return false;
            }
            return true;
        }
    };
};

#endif // !__UTIL_HPP__